/*
 * Copyright (c) 2010, okazoh_tk. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  - Neither the name of the copyright holder nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "alkes/graph/ILayouter.h"

namespace alkes {

ILayouter::ILayouter()
: padding_top_(0)
, padding_bottom_(0)
, padding_left_(0)
, padding_right_(0)
, margin_top_(0)
, margin_bottom_(0)
, margin_left_(0)
, margin_right_(0)
, halign_(AL_HALIGN_LEFT)
, valign_(AL_VALIGN_TOP)
{
}

ILayouter::~ILayouter()
{
}

void ILayouter::setPadding(int16_t top, int16_t bottom, int16_t left, int16_t right)
{
    padding_top_ = top;
    padding_bottom_ = bottom;
    padding_left_ = left;
    padding_right_ = right;
}

void ILayouter::setPaddingTop(int16_t top)
{
    padding_top_ = top;
}

void ILayouter::setPaddingBottom(int16_t bottom)
{
    padding_bottom_ = bottom;
}

void ILayouter::setPaddingLeft(int16_t left)
{
    padding_left_ = left;
}

void ILayouter::setPaddingRight(int16_t right)
{
    padding_right_ = right;
}

int16_t ILayouter::getPaddingTop() const
{
    return padding_top_;
}

int16_t ILayouter::getPaddingBottom() const
{
    return padding_bottom_;
}

int16_t ILayouter::getPaddingLeft() const
{
    return padding_left_;
}

int16_t ILayouter::getPaddingRight() const
{
    return padding_right_;
}

void ILayouter::setMargin(int16_t top, int16_t bottom, int16_t left, int16_t right)
{
    margin_top_ = top;
    margin_bottom_ = bottom;
    margin_left_ = left;
    margin_right_ = right;
}

void ILayouter::setMarginTop(int16_t top)
{
    margin_top_ = top;
}

void ILayouter::setMarginBottom(int16_t bottom)
{
    margin_bottom_ = bottom;
}

void ILayouter::setMarginLeft(int16_t left)
{
    margin_left_ = left;
}

void ILayouter::setMarginRight(int16_t right)
{
    margin_right_ = right;
}

int16_t ILayouter::getMarginTop() const
{
    return margin_top_;
}

int16_t ILayouter::getMarginBottom() const
{
    return margin_bottom_;
}

int16_t ILayouter::getMarginLeft() const
{
    return margin_left_;
}

int16_t ILayouter::getMarginRight() const
{
    return margin_right_;
}

void ILayouter::setHorizontalAlign(HorizontalAlign halign)
{
    halign_ = (int8_t)halign;
}

HorizontalAlign ILayouter::getHorizontalAlign() const
{
    return (HorizontalAlign)halign_;
}

void ILayouter::setVerticalAlign(VerticalAlign valign)
{
    valign_ = (int8_t)valign;
}

VerticalAlign ILayouter::getVerticalAlign() const
{
    return (VerticalAlign)valign_;
}

void ILayouter::calcLayout(HorizontalAlign halign, const RectSize& outer_rect, const RectSize& inner_rect, Point2D::value_type& x)
{
    switch (halign)
    {
    case AL_HALIGN_CENTER:
        x = (outer_rect.width - inner_rect.width) >> 1;
        break;
    case AL_HALIGN_RIGHT:
        x = outer_rect.width - inner_rect.width;
        break;
    default:
        x = 0;
        break;
    }
}

void ILayouter::calcLayout(HorizontalAlign halign, const Rect& outer_rect, const RectSize& inner_rect, Point2D::value_type& x)
{
    calcLayout(halign, URectSize(outer_rect), inner_rect, x);
    x += outer_rect.x;
}

void ILayouter::calcLayout(VerticalAlign valign, const RectSize& outer_rect, const RectSize& inner_rect, Point2D::value_type& y)
{
    switch (valign)
    {
    case AL_VALIGN_CENTER:
        y = (outer_rect.height - inner_rect.height) >> 1;
        break;
    case AL_VALIGN_BOTTOM:
        y = outer_rect.height - inner_rect.height;
        break;
    default:
        y = 0;
        break;
    }
}

void ILayouter::calcLayout(VerticalAlign valign, const Rect& outer_rect, const RectSize& inner_rect, Point2D::value_type& y)
{
    calcLayout(valign, URectSize(outer_rect), inner_rect, y);
    y += outer_rect.y;
}

void ILayouter::calcLayout(HorizontalAlign halign, VerticalAlign valign, const RectSize& outer_rect, const RectSize& inner_rect, Point2D& new_position)
{
    calcLayout(halign, outer_rect, inner_rect, new_position.x);
    calcLayout(valign, outer_rect, inner_rect, new_position.y);
}

void ILayouter::beginLayout(const Rect& rect)
{
    Rect final_rect = rect;

    final_rect.x += padding_left_;
    final_rect.y += padding_top_;
    final_rect.width -= (padding_left_ + padding_right_);
    final_rect.height -= (padding_top_ + padding_bottom_);

    onBeginLayout(final_rect);
}

void ILayouter::endLayout()
{
    onEndLayout();
}

void ILayouter::calcPosition(uint32_t index, const RectSize& size, Point2D& new_position)
{
    onCalcPosition(index, size, new_position);
}

}
